<template>
  <div class="modelListDrawer-container" :class="[visible ? 'show' : 'hide']">
    <div class="modelListDrawer-body">
      <div class="header">
        模型列表<a-icon type="close" @click="handleClose()" />
      </div>
      <div class="body">
        <div class="search-condition">
          <a-input-search
            v-model.trim="keyWord"
            @search="filterTreeData()"
            style="width: 100%"
            placeholder="请输入关键字"
          />
        </div>
        <div class="tree-container">
          <a-spin :spinning="spinning">
            <a-empty v-if="treeData.length == 0" :description="false" />
            <!-- -->
            <a-tree
              v-else
              v-model="checkedKeys"
              checkable
              show-icon
              :expanded-keys="expandedKeys"
              :auto-expand-parent="autoExpandParent"
              :selected-keys="selectedKeys"
              :tree-data="treeData"
              @expand="onExpand"
              @select="onSelect"
              @check="onCheck"
              :load-data="onLoadData"
              :replaceFields="{
                children: 'subNodes',
                title: 'nodeName',
                key: 'nodeId',
              }"
            >
              <!-- 自定义图标 -->
              <template slot="custom" slot-scope="{ subNodes }">
                <icon-font
                  :type="
                    subNodes.length > 0 ? 'icon-wenjianjia-' : 'icon-a-moxing1'
                  "
                />
              </template>
              <template slot="title" slot-scope="{ nodeName }">
                <span :title="nodeName">
                  {{ nodeName }}
                </span>
              </template>
            </a-tree>
          </a-spin>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import {
  addAttributeByKey,
  flatTreeData,
  getPathByKey,
  getParentNodeByKey,
} from "@/utils/util.js";
import cloneDeep from "lodash.clonedeep";
import { Icon } from "ant-design-vue";
import iconfrontjs from "@/assets/IconFont/iconfont.js";
const iconFrontUrl = iconfrontjs;
const IconFont = Icon.createFromIconfontCN({
  scriptUrl: iconFrontUrl,
});
import {
  getModalTreeById,
  dataSetFileTreeNodes,
  getModalTreeElemIdsById,
} from "@/api/bim";
export default {
  name: "modelListDrawer",
  inject: ["currentProject", "sceneSource"],
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  components: {
    IconFont,
  },
  data() {
    return {
      keyWord: "",
      expandedKeys: [],
      autoExpandParent: true,
      checkedKeys: [],
      selectedKeys: [],
      treeData: [],
      cloneTreeData: [],
      spinning: false,
    };
  },
  watch: {
    visible: {
      handler(val) {
        if (val) {
          this.$nextTick((_) => {
            this.getData();
          });
        }
      },
      immediate: true,
    },
  },
  mounted() {},
  methods: {
    //请求属性数据
    getData() {
      this.spinning = true;
      return new Promise((resolve, reject) => {
        let { foreignUuid } = this.currentProject();
        if (!foreignUuid) {
          return;
        }
        getModalTreeById({ projId: foreignUuid })
          .then((res) => {
            let tree = res?.data?.subNodes ?? [];

            let filterData = addAttributeByKey(
              null,
              "scopedSlots",
              { icon: "custom" },
              tree,
              "subNodes"
            );
            this.treeData = filterData;
            this.cloneTreeData = cloneDeep(filterData);
            let nodeId = tree.map((v) => v.nodeId).filter((v) => v);
            this.checkedKeys = nodeId;
            this.expandedKeys = [];
            resolve();
          })
          .catch((_) => {
            this.treeData = [];
            this.checkedKeys = [];
            this.expandedKeys = [];
            this.cloneTreeData = [];
            reject();
          })
          .finally((_) => {
            this.spinning = false;
          });
      });
    },

    //查询子节点数据
    onLoadData(treeNode) {
      return new Promise((resolve, reject) => {
        let { dataSetId, subNodes = [] } = treeNode.dataRef;
        if (dataSetId && subNodes.length == 0) {
          this.getChildrenData(dataSetId)
            .then((res) => {
              let tree = res?.data ?? [];
              let filterData = addAttributeByKey(
                null,
                "scopedSlots",
                { icon: "custom" },
                tree,
                "subNodes"
              );
              treeNode.dataRef.subNodes = filterData;
              this.treeData = [...this.treeData];
              this.cloneTreeData = cloneDeep(this.treeData);
              resolve();
            })
            .catch((_) => {
              reject();
            });
        } else {
          resolve();
        }
      });
    },

    getChildrenData(dataSetId = "") {
      if (!dataSetId) {
        return;
      }
      return new Promise((resolve, reject) => {
        dataSetFileTreeNodes({ dataSetId })
          .then((res) => {
            resolve(res);
          })
          .catch((_) => {
            reject();
          });
      });
    },

    //设置构建颜色
    setElemColor(dataSetId, elemIds = [], color) {
      var elemAttr = new BlackHole3D.REElemAttr();
      elemAttr.dataSetId = dataSetId;
      elemAttr.elemIdList = elemIds;
      elemAttr.elemClr = color;
      BlackHole3D.BIM.setElemAttr(elemAttr);
    },

    //设置构件透明度
    setElemAlpha(dataSetId, elemIds = [], elemAlpha) {
      BlackHole3D.BIM.setElemAlpha(dataSetId, elemIds, elemAlpha);
    },

    onExpand(expandedKeys) {
      this.expandedKeys = expandedKeys;
      this.autoExpandParent = false;
    },

    //监听复选框选中
    async onCheck(checkedKeys, info) {
      this.checkedKeys = checkedKeys;
      let { checked } = info;
      let { childNodeIds, dataSetId } = await this.getElemIds(info);
      try {
        // BlackHole3D.BIM.resetElemAttr(dataSetId, []);
        if (checked) {
          this.setElemAlpha(dataSetId, childNodeIds, 255);
        } else {
          this.setElemAlpha(dataSetId, childNodeIds, 0);
        }
      } catch (error) {}
    },

    //监听树形选择
    async onSelect(selectedKeys, info) {
      this.selectedKeys = selectedKeys;
      let { childNodeIds, dataSetId, notParentNode } = await this.getElemIds(
        info
      );
      //相机定位到指定构件;
      try {
        let bimIds = flatTreeData([info.node.dataRef], "subNodes");
        let elemIdList = bimIds.map((v) => v.nodeId).filter((v) => v);
        if (elemIdList.length > 0) {
          var locIDList = [{ dataSetId, elemIdList: childNodeIds ?? [] }];
          if (!notParentNode) {
            BlackHole3D.Camera.setCamLocateToElem(
              locIDList,
              1,
              BlackHole3D.RECamDirEm.CAM_DIR_DEFAULT
            );
            BlackHole3D.BIM.resetElemAttr(dataSetId, []);
          }

          //   this.setElemColor(
          //     dataSetId,
          //     childNodeIds ?? [],
          //     new BlackHole3D.REColor(255, 0, 0, 190)
          //   );
        }
      } catch (error) {}
    },

    //查询节点对应的构件id集合
    getElemIds(info = {}) {
      let { node } = info;
      let { nodeId, subNodes } = node.dataRef;
      let parentNode = getParentNodeByKey(
        nodeId,
        "nodeId",
        this.treeData,
        "subNodes"
      );
      let { dataSetId } =
        getPathByKey(nodeId, "nodeId", this.treeData, false, "subNodes")?.[0] ??
        {};
      let flatData = flatTreeData([node.dataRef], "subNodes");
      let dataSets = flatData
        .filter((v) => v.nodeId != nodeId || !subNodes || subNodes.length == 0)
        .map((v) => v.nodeId)
        .map((v) => {
          return {
            dataSetId,
            childNodeId: v,
          };
        });
      return new Promise((resolve, reject) => {
        if (!parentNode) {
          var backDepth = 2.0;
          var locType = BlackHole3D.RECamDirEm.CAM_DIR_DEFAULT;
          BlackHole3D.Camera.setCamLocateToDataSet(
            dataSetId,
            backDepth,
            locType
          );
          resolve({ childNodeIds: [], dataSetId, notParentNode: true });
          return;
        }
        getModalTreeElemIdsById({ dataSets })
          .then((res) => {
            let { data } = res;
            resolve(data?.[0] ?? { childNodeIds: [] });
          })
          .catch((_) => {
            resolve([]);
          })
          .finally((_) => {});
      });
    },

    //过滤树形数据
    filterTreeData() {
      let { keyWord } = this;
      let cTreeData = cloneDeep(this.cloneTreeData);
      this.treeData = this.filterTree(cTreeData, "subNodes", (node) =>
        node.nodeName.includes(keyWord)
      );
      let flatData = flatTreeData(this.treeData, "subNodes");
      if (keyWord.trim() == "") {
        this.expandedKeys = cTreeData?.[0]?.nodeId
          ? [cTreeData?.[0]?.nodeId]
          : [];
      } else {
        this.expandedKeys = flatData.map((v) => v.nodeId);
      }
    },

    //过滤树形数据
    filterTree(data, children = "children", filterFunc) {
      return data
        .filter((node) => {
          // 如果当前节点符合条件，直接返回true
          if (filterFunc(node)) {
            return true;
          }
          // 如果当前节点有子节点，递归过滤子节点
          if (node[children]) {
            node[children] = this.filterTree(
              node[children],
              children,
              filterFunc
            );
            // 如果过滤后的子节点不为空，说明当前节点需要保留
            return node[children].length > 0;
          }
          // 当前节点不符合条件，也没有子节点或子节点不符合条件，返回false
          return false;
        })
        .map((node) => {
          // 创建新对象，避免修改原始数据
          return {
            ...node,
            [children]: node[children]
              ? this.filterTree(node[children], children, filterFunc)
              : [],
          };
        });
    },

    handleClose() {
      //重置bim状态
      try {
        let { treeData } = this;
        let dataSetIds = treeData.map((v) => v.dataSetId);
        dataSetIds.forEach((v) => {
          BlackHole3D.BIM.resetElemAttr(v, []);
        });
      } catch (error) {}
      this.$emit("update:visible", false);
      this.$emit("close", false);
    },
  },
};
</script>
<style lang="less" scoped>
.modelListDrawer-container {
  position: absolute;
  width: 300px;
  height: 100%;
  top: 0;
  pointer-events: none;
  transition: 0.3s;
  left: 10px;
  box-sizing: border-box;
  padding: 16px 0 20px 0;
  z-index: 99;
  &.hide {
    left: -100%;
  }
  .modelListDrawer-body {
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 6px;
    pointer-events: all;
    .header {
      flex-shrink: 0;
      height: 36px;
      background: #f0f0f0;
      border-radius: 6px 6px 0px 0px;
      border: 1px solid #d9d9d9;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      padding: 0 16px;
      font-size: 16px;
      color: #333333;
      position: relative;
      .anticon-close {
        color: #8c8c8c;
        font-size: 15px;
        cursor: pointer;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        right: 10px;
      }
    }
    .body {
      flex: 1;
      background: #fff;
      padding: 0 0 10px 0;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      .search-condition {
        flex-shrink: 0;
        padding: 16px 16px 4px 16px;
        position: relative;
        input {
          padding-right: 36px;
        }
        .anticon {
          color: #8c8c8c;
          position: absolute;
          right: 28px;
          font-size: 20px;
          cursor: pointer;
          top: 20px;
        }
      }
      .tree-container {
        flex: 1;
        padding: 0 10px;
        overflow: auto;
        overflow-x: hidden;
        position: relative;
        /deep/.ant-tree {
          li {
            width: 100%;
            .ant-tree-node-content-wrapper {
              position: relative;
              width: calc(100% - 34px);
              .ant-tree-iconEle {
                color: #f3ab1f;
                font-size: 16px;
              }
              .ant-tree-title {
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                display: inline-block;
                max-width: calc(100% - 40px);
              }
            }
          }
        }
        /deep/.ant-empty {
          position: absolute;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
        }
      }
    }
  }
}
</style>
